// 版权所有2010 Go作者。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// utf16包实现UTF-16序列的编码和解码。
package utf16

// 条件replacementChar==unicode。ReplacementChar和
// maxRune==unicode。MaxRune在测试中得到了验证。
// 在本地定义它们可以避免依赖于包unicode的此包。

const (
	replacementChar = '\uFFFD'     // Unicode替换字符
	maxRune         = '\U0010FFFF' // 最大有效Unicode代码点。
)

const (
	// 0xd800-0xdc00对一对中的高10位进行编码。
	// 0xdc00-0xe000对一对中的低10位进行编码。
	// 该值是这20位加上0x10000。
	surr1 = 0xd800
	surr2 = 0xdc00
	surr3 = 0xe000

	surrSelf = 0x10000
)

// IsSurrogate报告指定的Unicode代码点
// 是否可以出现在代理项对中。
func IsSurrogate(r rune) bool {
	return surr1 <= r && r < surr3
}

// DecodeRune返回代理项对的UTF-16解码。
// 如果该对不是有效的UTF-16代理项对，DecodeRune将返回
// Unicode替换码点U+FFFD。
func DecodeRune(r1, r2 rune) rune {
	if surr1 <= r1 && r1 < surr2 && surr2 <= r2 && r2 < surr3 {
		return (r1-surr1)<<10 | (r2 - surr2) + surrSelf
	}
	return replacementChar
}

// EncodeRune返回给定符文的UTF-16代理项对r1、r2。
// 如果符文不是有效的Unicode码点或不需要编码，
// EncodeRune返回U+FFFD，U+FFFD。
func EncodeRune(r rune) (r1, r2 rune) {
	if r < surrSelf || r > maxRune {
		return replacementChar, replacementChar
	}
	r -= surrSelf
	return surr1 + (r>>10)&0x3ff, surr2 + r&0x3ff
}

// Encode返回Unicode码点序列s的UTF-16编码。
func Encode(s []rune) []uint16 {
	n := len(s)
	for _, v := range s {
		if v >= surrSelf {
			n++
		}
	}

	a := make([]uint16, n)
	n = 0
	for _, v := range s {
		switch {
		case 0 <= v && v < surr1, surr3 <= v && v < surrSelf:
			// 正常符文
			a[n] = uint16(v)
			n++
		case surrSelf <= v && v <= maxRune:
			// 需要代理序列
			r1, r2 := EncodeRune(v)
			a[n] = uint16(r1)
			a[n+1] = uint16(r2)
			n += 2
		default:
			a[n] = uint16(replacementChar)
			n++
		}
	}
	return a[:n]
}

// Decode返回UTF-16编码s表示的Unicode码点序列。
func Decode(s []uint16) []rune {
	a := make([]rune, len(s))
	n := 0
	for i := 0; i < len(s); i++ {
		switch r := s[i]; {
		case r < surr1, surr3 <= r:
			// 正常符文
			a[n] = rune(r)
		case surr1 <= r && r < surr2 && i+1 < len(s) &&
			surr2 <= s[i+1] && s[i+1] < surr3:
			// 有效代理序列
			a[n] = DecodeRune(rune(r), rune(s[i+1]))
			i++
		default:
			// 代理项序列
			a[n] = replacementChar
		}
		n++
	}
	return a[:n]
}
